Solving Minimum Steps (BFS) and Probability (DP) problems.
Beginning from location (0,0) on an infinite board, what is the minimum number of steps needed for a knight to get to some other arbitrary location (x,y)?
Constraints: $1 \le x, y \le 8$
This problem asks for the **minimum number of steps**, which immediately suggests a **Breadth-First Search (BFS)**.
A knight moves in an 'L' shape: 2 squares in one direction (horizontal or vertical) and 1 square in the perpendicular direction. From $(0, 0)$, the possible moves are:
For a general graph, Time is $O(V + E)$ (Vertices + Edges). On a chessboard, we can approximate the search space to be the area reachable within the minimum number of steps $M$.
Time: $O(M^2)$ (approximated search space)
Space: $O(M^2)$ (for the Visited Set and Queue)
function bfs() {
// Queue stores {x, y, steps}
while (queue.length > 0) {
let {x, y, steps} = queue.shift();
if (x === targetX && y === targetY) {
return steps; // Found shortest path!
}
// Explore 8 moves
for (let i = 0; i < 8; i++) {
let nextX = x + DX[i];
let nextY = y + DY[i];
let key = `${nextX},${nextY}`;
if (!visited.has(key)) {
visited.add(key);
queue.push({x: nextX, y: nextY, steps: steps + 1});
}
}
}
}
Calculate the probability that a knight, starting at $(R, C)$ on an $N \times N$ board, remains on the board after exactly $K$ moves, where each move is random.
Constraints: $1 \le N \le 25, 0 \le K \le 100$.
We use Dynamic Programming because the probability of the knight being at a certain square at step $k$ depends only on the probabilities of being at its neighboring squares at step $k-1$.
State Definition:
$DP[r][c]$ = Probability the knight is at $(r, c)$ after the current number of steps.
Transition:
The new probability $DP[r][c]$ is calculated by summing $\mathbf{1/8 \times \text{prevDP}[r'][c']}$ for all 8 positions $(r', c')$ from which the knight could jump to $(r, c)$ in one move.
function calculateKnightProbability(n, k, startR, startC) {
if (k === 0) { return 1.0; }
// DP table: probability of being at (r, c)
let prevDp = Array(n).fill(0).map(() => Array(n).fill(0));
// Base case: 100% probability at start position
if (startR >= 0 && startR < n && startC >= 0 && startC < n) {
prevDp[startR][startC] = 1.0;
} else {
return 0.0;
}
// Knight's moves (same as before)
const DX = [1, 1, 2, 2, -1, -1, -2, -2];
const DY = [2, -2, 1, -1, 2, -2, 1, -1];
for (let s = 1; s <= k; s++) {
let currentDp = Array(n).fill(0).map(() => Array(n).fill(0));
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// Check all 8 possible previous positions (r_prev, c_prev)
for (let i = 0; i < 8; i++) {
const prevR = r - DX[i];
const prevC = c - DY[i];
// Check if the previous position was on the board
if (prevR >= 0 && prevR < n && prevC >= 0 && prevC < n) {
// The probability of reaching (r, c) is the sum of probabilities
// from all valid previous spots, multiplied by the move chance (1/8)
currentDp[r][c] += prevDp[prevR][prevC] * 0.125;
}
}
}
}
prevDp = currentDp; // Move forward one step
}
// Sum all probabilities in the final DP table
let totalProbability = 0;
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
totalProbability += prevDp[r][c];
}
}
return totalProbability;
}